﻿// -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	SmartLib
//  File name:	Expirable.cs
//  Developer:	Igor Solomatov
//  Created:	20.12.2014
// 
// -------------------- iSharePoint -------------------- //

using System;

namespace Smart
{
	public class Expirable<TExpirable> where TExpirable : class
	{
		protected object CurrentLock;

		protected TExpirable Current;

		protected int CurrentExpiry;

		protected readonly int ExpirationTimeout;

		public Expirable(int expirationTimeout)
		{
			CurrentLock = new Object();
			CurrentExpiry = Environment.TickCount - 1;
			Current = null;
			ExpirationTimeout = expirationTimeout;
		}

		public TExpirable Ensure(Func<TExpirable> loader)
		{
			// tick can overflow, but (CurrentExpiry - tick > 0) will work in any cases
			unchecked
			{
				var tick = Environment.TickCount;
				var result = Current;
				if (CurrentExpiry - tick > 0) return result;

				lock (CurrentLock)
				{
					tick = Environment.TickCount;
					result = Current;
					if (CurrentExpiry - tick > 0) return result;

					Current = result = loader();
					CurrentExpiry = Environment.TickCount + ExpirationTimeout;
				}

				return result;
			}
		}
	}
}